/**
  ******************************************************************************
  * @author     Chris
  * @since      2024/7/1 20:44
  *
  * @file       hd_ina226.h
  * @brief      Header file of Xxx hardware driver.
  *
  * @note       This file contains the Xxx object declaration.
  *
  * @warning    None.
  ******************************************************************************
  * Change Logs:
  *   Date          Author       Notes
  *   2024/7/1     Chris        the first version
  *
  ******************************************************************************
  */


#ifndef JLC_SKY_INA226_H
#define JLC_SKY_INA226_H

#include "pd_i2c.h"

struct INA226Vtbl;

/** @defgroup Object properties
  * @{
  */
typedef struct {
    I2C *i2c;
    
    // INA226 virtual table
    struct INA226Vtbl* vptr;
} INA226;
/**
 * @}
 */

/** @defgroup Object virtual table definition
  * @{
  */
struct INA226Vtbl {
    void (*init)(const INA226 *this);

    uint8_t (*read_shunt)(const INA226 *this, uint16_t *shuntVoltage);

    uint8_t (*read_bus)(const INA226 *this, uint16_t *busVoltage);

    uint8_t (*read_power)(const INA226 *this, uint16_t *power);

    uint8_t (*read_current)(const INA226 *this, uint16_t *current);

    uint8_t (*read_manu_id)(const INA226 *this, uint16_t *id);

    uint8_t (*read_die_id)(const INA226 *this, uint16_t *id);

    uint8_t (*read_data16)(const INA226 *this, uint8_t regAddr, uint16_t *regVal);

    uint8_t (*write_data16)(const INA226 *this, uint8_t regAddr, uint16_t *regVal);
};
/**
 * @}
 */

/** @defgroup Object constructor and member function declaration
  * @{
  */ 
void INA226_constructor(INA226 *this, I2C *i2c);
/**
 * @}
 */

/** @defgroup Object virtual table function implementation
  * @{
  */
static inline void INA226_init(const INA226 *this) {
    this->vptr->init(this);
}

static inline uint8_t INA226_readShunt(const INA226 *this, uint16_t *shuntVoltage) {
    return this->vptr->read_shunt(this, shuntVoltage);
}

static inline uint8_t INA226_readBus(const INA226 *this, uint16_t *busVoltage) {
    return this->vptr->read_bus(this, busVoltage);
}

static inline uint8_t INA226_readPower(const INA226 *this, uint16_t *power) {
    return this->vptr->read_power(this, power);
}

static inline uint8_t INA226_readCurrent(const INA226 *this, uint16_t *current) {
    return this->vptr->read_current(this, current);
}

static inline uint8_t INA226_readManuId(const INA226 *this, uint16_t *id) {
    return this->vptr->read_manu_id(this, id);
}

static inline uint8_t INA226_readDieId(const INA226 *this, uint16_t *id) {
    return this->vptr->read_die_id(this, id);
}

static inline uint8_t INA226_readData16(const INA226 *this, uint8_t regAddr, uint16_t *regVal) {
    return this->vptr->read_data16(this, regAddr, regVal);
}

static inline uint8_t INA226_writeData16(const INA226 *this, uint8_t regAddr, uint16_t *regVal) {
    return this->vptr->write_data16(this, regAddr, regVal);
}
/**
 * @}
 */  


#define INA226_SLAVE_ADDR       0x44    // 0b100xxxx, see INA226 datasheet chapter 7.5.5.1.
                                        // The A0, A1 pull-down to ground, the slave address should be
                                        // 0x40, but 0x44.

#define INA226_CONFIG           0x00    // 0x0000
#define INA226_SHUNT_VOLTAGE    0x01    // 0x0000
#define INA226_BUS_VOLTAGE      0x02    // 0x0000
#define INA226_POWER            0x03    // 0x0000
#define INA226_CURRENT          0x04    // 0x0000
#define INA226_CALIBRATION      0x05    // 0x0000
#define INA226_MASK_ENABLE      0x06    // 0x0000
#define INA226_ALERT_LIMIT      0x07    // 0x0000
#define INA226_MANU_ID          0xFE    // 0x5449
#define INA226_DIE_ID           0xFF    // 0x2260


#endif //JLC_SKY_INA226_H
